{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "be8b4981",
   "metadata": {},
   "source": [
    "# 数据准备-liepin-PM"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf22335a",
   "metadata": {},
   "source": [
    "## 请求页面准备\n",
    "> 1. 找到页面的数据API接口\n",
    "> 2. 提供正确的用户请求酬载（payload）\n",
    "> 3. 准备请求的headers，增加cookie信息（用户登录之后的cookie），保证数据的合理性\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "e2c79de4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请输入你要查询的职位：插画师\n"
     ]
    }
   ],
   "source": [
    "用户输入职位 = input(\"请输入你要查询的职位：\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "70830719",
   "metadata": {},
   "outputs": [],
   "source": [
    "城市编码 = {\n",
    "    '北京':'010',\n",
    "    '上海':'020',\n",
    "    '广州':'050020',\n",
    "    '深圳':'050090'\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "1f3b6a17",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请输入你要查询的地区：深圳\n"
     ]
    }
   ],
   "source": [
    "用户输入地区 = input(\"请输入你要查询的地区：\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "c6f6861b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import json\n",
    "\n",
    "url = \"https://apic.liepin.com/api/com.liepin.searchfront4c.pc-search-job\"\n",
    "payload = {\n",
    "    \"data\": {\n",
    "        \"mainSearchPcConditionForm\": {\n",
    "            \"city\": 用户输入地区,\n",
    "            \"dq\": 用户输入地区,\n",
    "            \"pubTime\": \"\",\n",
    "            \"currentPage\": 0,\n",
    "            \"pageSize\": 40,\n",
    "            \"key\": 用户输入职位,\n",
    "            \"suggestTag\": \"\",\n",
    "            \"workYearCode\": \"0\",\n",
    "            \"compId\": \"\",\n",
    "            \"compName\": \"\",\n",
    "            \"compTag\": \"\",\n",
    "            \"industry\": \"\",\n",
    "            \"salary\": \"\",\n",
    "            \"jobKind\": \"\",\n",
    "            \"compScale\": \"\",\n",
    "            \"compKind\": \"\",\n",
    "            \"compStage\": \"\",\n",
    "            \"eduLevel\": \"\"\n",
    "        },\n",
    "        \"passThroughForm\": {\n",
    "            \"scene\": \"input\",\n",
    "            \"skId\": \"\",\n",
    "            \"fkId\": \"\",\n",
    "            \"ckId\": \"h2c8pxojavrmo1w785z7ueih2ybfpux8\",\n",
    "            \"suggest\": None\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "77fdef0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set the headers\n",
    "headers = {\n",
    "    'Accept': 'application/json, text/plain, */*',\n",
    "    'Accept-Encoding': 'gzip, deflate, br',\n",
    "    'Accept-Language': 'zh-CN,zh;q=0.9',\n",
    "    'Cache-Control': 'no-cache',\n",
    "    'Connection': 'keep-alive',\n",
    "    'Content-Length': '412',\n",
    "    'Content-Type': 'application/json;charset=UTF-8;',\n",
    "    'Cookie':'inited_user=b2e8d9b444db947ff1d6e508a4eabb21; __gc_id=483dfeb545a7462a8aca2e0ddb6b3b77; _ga=GA1.1.136794046.1681903505; __uuid=1681903545566.81; need_bind_tel=false; c_flag=27079ec7153d898c60c1de3825710c9e; imClientId=bdd7042bddfede3fa12bac537377bfad; imId=bdd7042bddfede3f3e4f5f0f695234e5; imClientId_0=bdd7042bddfede3fa12bac537377bfad; imId_0=bdd7042bddfede3f3e4f5f0f695234e5; new_user=false; XSRF-TOKEN=v4DBRlmJTwK56eGBRcxX0g; __tlog=1686136308804.81%7C00000000%7C00000000%7Cs_o_007%7Cs_o_007; Hm_lvt_a2647413544f5a04f00da7eee0d5e200=1684927941,1685531164,1685606060,1686136309; UniqueKey=5c2b221c3cc6c043a9dba665e9526a14; liepin_login_valid=0; lt_auth=6esOaCcBxlX%2FsXfQj2JcsPtL3NOvVj3LpnUNjRsDhtfoWvbk4P%2FmQAmPr7gH%2FioIqxpyIf0zMLb2M%2Bn9z3BI7UoU%2B1Gkk565t%2FOz1HsKTuIxdPbw1%2F30msjSRJYknHAKwXZhp3gRxUyjsi0yW5fT2WP1t5nX342my%2FP0iCyWqBg8; user_roles=0; user_photo=5f8fa3b979c7cc70efbf445908u.png; user_name=%E6%B8%A9%E6%AC%A3%E6%AC%A3; access_system=C; inited_user=b2e8d9b444db947ff1d6e508a4eabb21; imApp_0=1; acw_tc=ac11000116861414186824548e00cbb5cf288c5bff9975228d9caba91fba7d; __session_seq=9; __uv_seq=9; Hm_lpvt_a2647413544f5a04f00da7eee0d5e200=1686141832; fe_im_socketSequence_new_0=6_6_6; fe_im_opened_pages=; fe_im_connectJson_0=%7B%220_5c2b221c3cc6c043a9dba665e9526a14%22%3A%7B%22socketConnect%22%3A%222%22%2C%22connectDomain%22%3A%22liepin.com%22%7D%7D; _ga_54YTJKWN86=GS1.1.1686141417.14.1.1686142153.0.0.0',\n",
    "    'Host': 'apic.liepin.com',\n",
    "    'Origin': 'https://www.liepin.com',\n",
    "    'Pragma': 'no-cache',\n",
    "    'Referer': 'https://www.liepin.com/',\n",
    "    'sec-ch-ua': '\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"',\n",
    "    'sec-ch-ua-mobile': '?0',\n",
    "    'sec-ch-ua-platform': '\"macOS\"',\n",
    "    'Sec-Fetch-Dest': 'empty',\n",
    "    'Sec-Fetch-Mode': 'cors',\n",
    "    'Sec-Fetch-Site': 'same-site',\n",
    "    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36',\n",
    "    'X-Client-Type': 'web',\n",
    "    'X-Fscp-Bi-Stat': '{\"location\": \"https://www.liepin.com/zhaopin/?inputFrom=www_index&workYearCode=0&key=%E4%BA%A7%E5%93%81%E7%BB%8F%E7%90%86&scene=input&ckId=htihov8m2frxgy6ywo2wsg2gncnydzlb&dq=\"}',\n",
    "    'X-Fscp-Fe-Version': '',\n",
    "    'X-Fscp-Std-Info': '{\"client_id\": \"40108\"}',\n",
    "    'X-Fscp-Trace-Id': 'fea335b6-f4a4-42fd-9bd8-6fe41ffec413',\n",
    "    'X-Fscp-Version': '1.1',\n",
    "    'X-Requested-With': 'XMLHttpRequest',\n",
    "    'X-XSRF-TOKEN': 'XMz5EHIASaeNsiKARaDj0g'\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a88dc86",
   "metadata": {},
   "source": [
    "### header的意义：用header封装自己是用户，来获取用户，而非python，以突破猎聘的反爬"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "3015bfe2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# send a POST request with headers 用自己的header发送POST请求\n",
    "r = requests.post(url, data=json.dumps(payload), headers=headers)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "e33353d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# extract the JSON data from the response\n",
    "response_data = r.json()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "6bc6561c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'flag': 1, 'data': {'data': {}, 'passThroughData': {'ckId': 'h2c8pxojavrmo1w785z7ueih2ybfpux8', 'scene': 'input', 'skId': 'h2c8pxojavrmo1w785z7ueih2ybfpux8', 'fkId': 'h2c8pxojavrmo1w785z7ueih2ybfpux8', 'sfrom': 'search_job_pc'}, 'pagination': {'totalCounts': 0, 'currentPage': 0, 'totalPage': 0, 'pageSize': 40, 'hasNext': False}}}\n"
     ]
    }
   ],
   "source": [
    "# example: print the number of job postings returned\n",
    "print(response_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "2619b0b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "eeef97f7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 向上取整\n",
    "page = math.ceil(response_data['data']['pagination']['totalCounts']/40)\n",
    "page"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "9bd13395",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "15.025"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "601/40"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "9e5801c8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.ceil(601/40)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "b0ee4b99",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14.25"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "570/40"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "b96fe540",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "15"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "math.ceil(570/40)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00d5fcb6",
   "metadata": {},
   "source": [
    "## 翻页获取数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "43043d51",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "response_df = []\n",
    "for i in range(page): # 需要判断页面的数据有多少页\n",
    "    payload['data']['mainSearchPcConditionForm']['currentPage']=i\n",
    "    # send a POST request with headers\n",
    "    r = requests.post(url, data=json.dumps(payload), headers=headers)\n",
    "\n",
    "    # extract the JSON data from the response\n",
    "    response_data = r.json()\n",
    "    print(response_data)\n",
    "    df = pd.json_normalize(response_data['data']['data']['jobCardList'])\n",
    "    response_df.append(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "4422f4cf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response_df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abf39634",
   "metadata": {},
   "source": [
    "## 数据整理成为表格\n",
    "> 1. pandas 中的concat方法（因为数据较规整）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "481b39e9",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "No objects to concatenate",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Input \u001b[1;32mIn [52]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconcat\u001b[49m\u001b[43m(\u001b[49m\u001b[43mresponse_df\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m      2\u001b[0m df\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\util\\_decorators.py:311\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    305\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m>\u001b[39m num_allow_args:\n\u001b[0;32m    306\u001b[0m     warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[0;32m    307\u001b[0m         msg\u001b[38;5;241m.\u001b[39mformat(arguments\u001b[38;5;241m=\u001b[39marguments),\n\u001b[0;32m    308\u001b[0m         \u001b[38;5;167;01mFutureWarning\u001b[39;00m,\n\u001b[0;32m    309\u001b[0m         stacklevel\u001b[38;5;241m=\u001b[39mstacklevel,\n\u001b[0;32m    310\u001b[0m     )\n\u001b[1;32m--> 311\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\core\\reshape\\concat.py:347\u001b[0m, in \u001b[0;36mconcat\u001b[1;34m(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)\u001b[0m\n\u001b[0;32m    143\u001b[0m \u001b[38;5;129m@deprecate_nonkeyword_arguments\u001b[39m(version\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, allowed_args\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mobjs\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m    144\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mconcat\u001b[39m(\n\u001b[0;32m    145\u001b[0m     objs: Iterable[NDFrame] \u001b[38;5;241m|\u001b[39m Mapping[Hashable, NDFrame],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    154\u001b[0m     copy: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[0;32m    155\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m DataFrame \u001b[38;5;241m|\u001b[39m Series:\n\u001b[0;32m    156\u001b[0m     \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m    157\u001b[0m \u001b[38;5;124;03m    Concatenate pandas objects along a particular axis with optional set logic\u001b[39;00m\n\u001b[0;32m    158\u001b[0m \u001b[38;5;124;03m    along the other axes.\u001b[39;00m\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    345\u001b[0m \u001b[38;5;124;03m    ValueError: Indexes have overlapping values: ['a']\u001b[39;00m\n\u001b[0;32m    346\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[1;32m--> 347\u001b[0m     op \u001b[38;5;241m=\u001b[39m \u001b[43m_Concatenator\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    348\u001b[0m \u001b[43m        \u001b[49m\u001b[43mobjs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    349\u001b[0m \u001b[43m        \u001b[49m\u001b[43maxis\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maxis\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    350\u001b[0m \u001b[43m        \u001b[49m\u001b[43mignore_index\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mignore_index\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    351\u001b[0m \u001b[43m        \u001b[49m\u001b[43mjoin\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mjoin\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    352\u001b[0m \u001b[43m        \u001b[49m\u001b[43mkeys\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mkeys\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    353\u001b[0m \u001b[43m        \u001b[49m\u001b[43mlevels\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlevels\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    354\u001b[0m \u001b[43m        \u001b[49m\u001b[43mnames\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnames\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    355\u001b[0m \u001b[43m        \u001b[49m\u001b[43mverify_integrity\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mverify_integrity\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    356\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcopy\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcopy\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    357\u001b[0m \u001b[43m        \u001b[49m\u001b[43msort\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msort\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    358\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    360\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m op\u001b[38;5;241m.\u001b[39mget_result()\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\core\\reshape\\concat.py:404\u001b[0m, in \u001b[0;36m_Concatenator.__init__\u001b[1;34m(self, objs, axis, join, keys, levels, names, ignore_index, verify_integrity, copy, sort)\u001b[0m\n\u001b[0;32m    401\u001b[0m     objs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(objs)\n\u001b[0;32m    403\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(objs) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m--> 404\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo objects to concatenate\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m    406\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m keys \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m    407\u001b[0m     objs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(com\u001b[38;5;241m.\u001b[39mnot_none(\u001b[38;5;241m*\u001b[39mobjs))\n",
      "\u001b[1;31mValueError\u001b[0m: No objects to concatenate"
     ]
    }
   ],
   "source": [
    "df = pd.concat(response_df)\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "1b7f1301",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'插画师'"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "key = payload['data']['mainSearchPcConditionForm']['key']\n",
    "key"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa71966a",
   "metadata": {},
   "source": [
    "## 数据存储"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "32998a40",
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "2a6a6ce5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "time.struct_time(tm_year=2023, tm_mon=6, tm_mday=7, tm_hour=20, tm_min=50, tm_sec=45, tm_wday=2, tm_yday=158, tm_isdst=0)"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "time.localtime()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "ad52ba55",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'67_2050'"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "output_time = str(time.localtime().tm_mon)\\\n",
    "             +str(time.localtime().tm_mday)+'_'\\\n",
    "             +str(time.localtime().tm_hour) \\\n",
    "             +str(time.localtime().tm_min)\n",
    "output_time "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "1d2de632",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [57]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 按照职位名称和时间导出文件\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[43mdf\u001b[49m\u001b[38;5;241m.\u001b[39mto_excel( key \u001b[38;5;241m+\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_liepin_\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m+\u001b[39moutput_time\u001b[38;5;241m+\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m.xlsx\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df' is not defined"
     ]
    }
   ],
   "source": [
    "# 按照职位名称和时间导出文件\n",
    "df.to_excel( key +'_liepin_'+output_time+'.xlsx')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6511a95",
   "metadata": {},
   "source": [
    "# 数据分析\n",
    "\n",
    "> 1. Pandas/Numpy\n",
    "> 2. Pyecharts(bokeh、matplotlab、seaborn、echarts、Tebleau)/更考虑用户的体验"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "ae96f73c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "af2682c2",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: '插画师_liepin_67_2050.xlsx'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "Input \u001b[1;32mIn [59]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread_excel\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkey\u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m_liepin_\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[43moutput_time\u001b[49m\u001b[38;5;241;43m+\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m.xlsx\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[0;32m      2\u001b[0m df\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\util\\_decorators.py:311\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    305\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m>\u001b[39m num_allow_args:\n\u001b[0;32m    306\u001b[0m     warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[0;32m    307\u001b[0m         msg\u001b[38;5;241m.\u001b[39mformat(arguments\u001b[38;5;241m=\u001b[39marguments),\n\u001b[0;32m    308\u001b[0m         \u001b[38;5;167;01mFutureWarning\u001b[39;00m,\n\u001b[0;32m    309\u001b[0m         stacklevel\u001b[38;5;241m=\u001b[39mstacklevel,\n\u001b[0;32m    310\u001b[0m     )\n\u001b[1;32m--> 311\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\io\\excel\\_base.py:457\u001b[0m, in \u001b[0;36mread_excel\u001b[1;34m(io, sheet_name, header, names, index_col, usecols, squeeze, dtype, engine, converters, true_values, false_values, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, parse_dates, date_parser, thousands, decimal, comment, skipfooter, convert_float, mangle_dupe_cols, storage_options)\u001b[0m\n\u001b[0;32m    455\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(io, ExcelFile):\n\u001b[0;32m    456\u001b[0m     should_close \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m--> 457\u001b[0m     io \u001b[38;5;241m=\u001b[39m \u001b[43mExcelFile\u001b[49m\u001b[43m(\u001b[49m\u001b[43mio\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mengine\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mengine\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    458\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m engine \u001b[38;5;129;01mand\u001b[39;00m engine \u001b[38;5;241m!=\u001b[39m io\u001b[38;5;241m.\u001b[39mengine:\n\u001b[0;32m    459\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m    460\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mEngine should not be specified when passing \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    461\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124man ExcelFile - ExcelFile already has the engine set\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    462\u001b[0m     )\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\io\\excel\\_base.py:1376\u001b[0m, in \u001b[0;36mExcelFile.__init__\u001b[1;34m(self, path_or_buffer, engine, storage_options)\u001b[0m\n\u001b[0;32m   1374\u001b[0m     ext \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxls\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1375\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m-> 1376\u001b[0m     ext \u001b[38;5;241m=\u001b[39m \u001b[43minspect_excel_format\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   1377\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\n\u001b[0;32m   1378\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m   1379\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m ext \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m   1380\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m   1381\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExcel file format cannot be determined, you must specify \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1382\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124man engine manually.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1383\u001b[0m         )\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\io\\excel\\_base.py:1250\u001b[0m, in \u001b[0;36minspect_excel_format\u001b[1;34m(content_or_path, storage_options)\u001b[0m\n\u001b[0;32m   1247\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(content_or_path, \u001b[38;5;28mbytes\u001b[39m):\n\u001b[0;32m   1248\u001b[0m     content_or_path \u001b[38;5;241m=\u001b[39m BytesIO(content_or_path)\n\u001b[1;32m-> 1250\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   1251\u001b[0m \u001b[43m    \u001b[49m\u001b[43mcontent_or_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mis_text\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\n\u001b[0;32m   1252\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m handle:\n\u001b[0;32m   1253\u001b[0m     stream \u001b[38;5;241m=\u001b[39m handle\u001b[38;5;241m.\u001b[39mhandle\n\u001b[0;32m   1254\u001b[0m     stream\u001b[38;5;241m.\u001b[39mseek(\u001b[38;5;241m0\u001b[39m)\n",
      "File \u001b[1;32mD:\\Anaconda\\lib\\site-packages\\pandas\\io\\common.py:798\u001b[0m, in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m    789\u001b[0m         handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(\n\u001b[0;32m    790\u001b[0m             handle,\n\u001b[0;32m    791\u001b[0m             ioargs\u001b[38;5;241m.\u001b[39mmode,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    794\u001b[0m             newline\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m    795\u001b[0m         )\n\u001b[0;32m    796\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    797\u001b[0m         \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[1;32m--> 798\u001b[0m         handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mioargs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    799\u001b[0m     handles\u001b[38;5;241m.\u001b[39mappend(handle)\n\u001b[0;32m    801\u001b[0m \u001b[38;5;66;03m# Convert BytesIO or file objects passed with an encoding\u001b[39;00m\n",
      "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '插画师_liepin_67_2050.xlsx'"
     ]
    }
   ],
   "source": [
    "df = pd.read_excel(key+'_liepin_'+output_time+'.xlsx')\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e14c166d",
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bf806de",
   "metadata": {},
   "source": [
    "## 筛选存在数据分析价值的列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "048c64d5",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [60]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m df_PM_gz \u001b[38;5;241m=\u001b[39m  \u001b[43mdf\u001b[49m[[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.labels\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.refreshTime\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.salary\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.dq\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.topJob\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.requireWorkYears\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.requireEduLevel\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compStage\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compName\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compIndustry\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compScale\u001b[39m\u001b[38;5;124m'\u001b[39m]]\n\u001b[0;32m      2\u001b[0m df_PM_gz\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df' is not defined"
     ]
    }
   ],
   "source": [
    "df_PM_gz =  df[['job.labels','job.refreshTime','job.title','job.salary','job.dq','job.topJob','job.requireWorkYears','job.requireEduLevel','comp.compStage','comp.compName','comp.compIndustry','comp.compScale']]\n",
    "df_PM_gz"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66931fa5",
   "metadata": {},
   "source": [
    "## 广州的PM地区分布"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "40af9bd5",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [61]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.dq\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mvalue_counts()\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "df_PM_gz['job.dq'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "6e2e2626",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [62]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m 地区 \u001b[38;5;241m=\u001b[39m [  i\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m1\u001b[39m]       \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.dq\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mvalue_counts()\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mtolist()[\u001b[38;5;241m1\u001b[39m:]]\n\u001b[0;32m      2\u001b[0m 地区\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "地区 = [  i.split('-')[1]       for i in df_PM_gz['job.dq'].value_counts().index.tolist()[1:]]\n",
    "地区"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "6c2a3f0f",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [63]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m 岗位个数 \u001b[38;5;241m=\u001b[39m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.dq\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mvalue_counts()\u001b[38;5;241m.\u001b[39mvalues\u001b[38;5;241m.\u001b[39mtolist()[\u001b[38;5;241m1\u001b[39m:]\n\u001b[0;32m      2\u001b[0m 广州_岗位个数\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "岗位个数 = df_PM_gz['job.dq'].value_counts().values.tolist()[1:]\n",
    "广州_岗位个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "1d6a1a77",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '广州地区' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [64]\u001b[0m, in \u001b[0;36m<cell line: 8>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyecharts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcharts\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Map\n\u001b[0;32m      5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyecharts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mfaker\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Faker\n\u001b[0;32m      7\u001b[0m c \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m      8\u001b[0m     Map()\n\u001b[1;32m----> 9\u001b[0m     \u001b[38;5;241m.\u001b[39madd(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m广州\u001b[39m\u001b[38;5;124m\"\u001b[39m, [\u001b[38;5;28mlist\u001b[39m(z) \u001b[38;5;28;01mfor\u001b[39;00m z \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(\u001b[43m广州地区\u001b[49m, 广州_岗位个数)], \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m广州\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m     10\u001b[0m     \u001b[38;5;241m.\u001b[39mset_global_opts(\n\u001b[0;32m     11\u001b[0m         title_opts\u001b[38;5;241m=\u001b[39mopts\u001b[38;5;241m.\u001b[39mTitleOpts(title\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mMap-广州地图\u001b[39m\u001b[38;5;124m\"\u001b[39m), visualmap_opts\u001b[38;5;241m=\u001b[39mopts\u001b[38;5;241m.\u001b[39mVisualMapOpts()\n\u001b[0;32m     12\u001b[0m     )\n\u001b[0;32m     13\u001b[0m     \u001b[38;5;241m.\u001b[39mrender( key\u001b[38;5;241m+\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_dq_map_地区分布_\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m+\u001b[39moutput_time\u001b[38;5;241m+\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.html\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m     14\u001b[0m )\n",
      "\u001b[1;31mNameError\u001b[0m: name '广州地区' is not defined"
     ]
    }
   ],
   "source": [
    "# 可视化：以可视化工具数据形态符合的数据进行输入\n",
    "\n",
    "from pyecharts import options as opts\n",
    "from pyecharts.charts import Map\n",
    "from pyecharts.faker import Faker\n",
    "\n",
    "c = (\n",
    "    Map()\n",
    "    .add(\"广州\", [list(z) for z in zip(广州地区, 广州_岗位个数)], \"广州\")\n",
    "    .set_global_opts(\n",
    "        title_opts=opts.TitleOpts(title=\"Map-广州地图\"), visualmap_opts=opts.VisualMapOpts()\n",
    "    )\n",
    "    .render( key+\"_dq_map_地区分布_\"+output_time+\".html\")\n",
    ")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2eeb9e36",
   "metadata": {},
   "source": [
    "## 职位分布\n",
    "\n",
    "* 知识点：dataframe字符串处理\n",
    "> 1. [pandas.series.str](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "b865f4c9",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [65]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m]\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    " df_PM_gz['job.title']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "7bdd1791",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [66]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 还要合并回去原来的行\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m][   df_PM_gz[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mstr\u001b[38;5;241m.\u001b[39mcontains(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m（\u001b[39m\u001b[38;5;124m'\u001b[39m)   ]\u001b[38;5;241m.\u001b[39mstr\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m（\u001b[39m\u001b[38;5;124m'\u001b[39m)\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m x:x[\u001b[38;5;241m0\u001b[39m])\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "# 还要合并回去原来的行\n",
    "df_PM_gz['job.title'][   df_PM_gz['job.title'].str.contains('（')   ].str.split('（').apply(lambda x:x[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "67ce6925",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [67]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 处理过一些，清洗后的数据\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m df_job_title \u001b[38;5;241m=\u001b[39m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m x:x\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m（\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m(\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m])\u001b[38;5;241m.\u001b[39mvalue_counts()\n\u001b[0;32m      3\u001b[0m df_job_title\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "# 处理过一些，清洗后的数据\n",
    "df_job_title = df_PM_gz['job.title'].apply(lambda x:x.split('（')[0].split('/')[0].split('(')[0]).value_counts()\n",
    "df_job_title"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "002d568f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_job_title' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [68]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_job_title\u001b[49m\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mtolist()\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_job_title' is not defined"
     ]
    }
   ],
   "source": [
    "df_job_title.index.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "02180275",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_job_title' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [69]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[43mdf_job_title\u001b[49m\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mtolist())\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_job_title' is not defined"
     ]
    }
   ],
   "source": [
    "len(df_job_title.index.tolist())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "e8c8f438",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_job_title' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [70]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_job_title\u001b[49m\u001b[38;5;241m.\u001b[39mvalues\u001b[38;5;241m.\u001b[39mtolist()\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_job_title' is not defined"
     ]
    }
   ],
   "source": [
    "df_job_title.values.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "24635f28",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [71]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 未处理字符串的数据（不太整洁和干净的数据）\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mvalue_counts()\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "# 未处理字符串的数据（不太整洁和干净的数据）\n",
    "df_PM_gz['job.title'].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "0a02f2bc",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_job_title' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [72]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 列表推导式\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m PM_title_words \u001b[38;5;241m=\u001b[39m [(  df_job_title\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mtolist()[i]   ,   df_job_title\u001b[38;5;241m.\u001b[39mvalues\u001b[38;5;241m.\u001b[39mtolist()[i]  )    \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m,\u001b[38;5;28mlen\u001b[39m(\u001b[43mdf_job_title\u001b[49m\u001b[38;5;241m.\u001b[39mindex\u001b[38;5;241m.\u001b[39mtolist())) ]\n\u001b[0;32m      3\u001b[0m PM_title_words\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_job_title' is not defined"
     ]
    }
   ],
   "source": [
    "# 列表推导式\n",
    "PM_title_words = [(  df_job_title.index.tolist()[i]   ,   df_job_title.values.tolist()[i]  )    for i in range(1,len(df_job_title.index.tolist())) ]\n",
    "PM_title_words"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "601ce6a9",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'PM_title_words' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [73]\u001b[0m, in \u001b[0;36m<cell line: 6>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyecharts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcharts\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WordCloud\n\u001b[0;32m      3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyecharts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mglobals\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SymbolType\n\u001b[0;32m      5\u001b[0m c \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m      6\u001b[0m     WordCloud()\n\u001b[1;32m----> 7\u001b[0m     \u001b[38;5;241m.\u001b[39madd(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43mPM_title_words\u001b[49m, word_size_range\u001b[38;5;241m=\u001b[39m[\u001b[38;5;241m20\u001b[39m, \u001b[38;5;241m100\u001b[39m], shape\u001b[38;5;241m=\u001b[39mSymbolType\u001b[38;5;241m.\u001b[39mDIAMOND)\n\u001b[0;32m      8\u001b[0m     \u001b[38;5;241m.\u001b[39mset_global_opts(title_opts\u001b[38;5;241m=\u001b[39mopts\u001b[38;5;241m.\u001b[39mTitleOpts(title\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mWordCloud-shape-diamond\u001b[39m\u001b[38;5;124m\"\u001b[39m))\n\u001b[0;32m      9\u001b[0m     \u001b[38;5;241m.\u001b[39mrender( key \u001b[38;5;241m+\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_wordcloud_map_岗位名称_\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m+\u001b[39m output_time\u001b[38;5;241m+\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.html\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m     10\u001b[0m )\n",
      "\u001b[1;31mNameError\u001b[0m: name 'PM_title_words' is not defined"
     ]
    }
   ],
   "source": [
    "from pyecharts import options as opts\n",
    "from pyecharts.charts import WordCloud\n",
    "from pyecharts.globals import SymbolType\n",
    "\n",
    "c = (\n",
    "    WordCloud()\n",
    "    .add(\"\", PM_title_words, word_size_range=[20, 100], shape=SymbolType.DIAMOND)\n",
    "    .set_global_opts(title_opts=opts.TitleOpts(title=\"WordCloud-shape-diamond\"))\n",
    "    .render( key +\"_wordcloud_map_岗位名称_\"+ output_time+\".html\")\n",
    ")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6dd926d7",
   "metadata": {},
   "source": [
    "## job.labels\n",
    "\n",
    "* 目标：统计labels的数量并做词云图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "692c0136",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [74]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.labels\u001b[39m\u001b[38;5;124m'\u001b[39m]\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    " df_PM_gz['job.labels']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "58da6bb3",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [75]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.labels\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mvalues\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    " df_PM_gz['job.labels'].values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "d607c892",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [76]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.labels\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m x:\u001b[38;5;28meval\u001b[39m(x))\u001b[38;5;241m.\u001b[39mtolist()\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "df_PM_gz['job.labels'].apply(lambda x:eval(x)).tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "cdd091f5",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [77]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 列表的推导式\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m PM_labels_list \u001b[38;5;241m=\u001b[39m [j     \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[43mdf_PM_gz\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.labels\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m x:\u001b[38;5;28meval\u001b[39m(x))\u001b[38;5;241m.\u001b[39mtolist()       \u001b[38;5;28;01mfor\u001b[39;00m j \u001b[38;5;129;01min\u001b[39;00m i    ]\n\u001b[0;32m      3\u001b[0m PM_labels_list\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "# 列表的推导式\n",
    "PM_labels_list = [j     for i in df_PM_gz['job.labels'].apply(lambda x:eval(x)).tolist()       for j in i    ]\n",
    "PM_labels_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "41a5b2f5",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'PM_labels_list' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [78]\u001b[0m, in \u001b[0;36m<cell line: 3>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 创建words\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m PM_labels_words \u001b[38;5;241m=\u001b[39m [ (i,PM_labels_list\u001b[38;5;241m.\u001b[39mcount(i)) \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mset\u001b[39m(\u001b[43mPM_labels_list\u001b[49m)]\n\u001b[0;32m      4\u001b[0m PM_labels_words\n",
      "\u001b[1;31mNameError\u001b[0m: name 'PM_labels_list' is not defined"
     ]
    }
   ],
   "source": [
    "# 创建words\n",
    "\n",
    "PM_labels_words = [ (i,PM_labels_list.count(i)) for i in set(PM_labels_list)]\n",
    "PM_labels_words"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "251470c9",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'PM_labels_words' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [79]\u001b[0m, in \u001b[0;36m<cell line: 7>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyecharts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcharts\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WordCloud\n\u001b[0;32m      4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyecharts\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mglobals\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SymbolType\n\u001b[0;32m      6\u001b[0m c \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m      7\u001b[0m     WordCloud()\n\u001b[1;32m----> 8\u001b[0m     \u001b[38;5;241m.\u001b[39madd(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43mPM_labels_words\u001b[49m, word_size_range\u001b[38;5;241m=\u001b[39m[\u001b[38;5;241m20\u001b[39m, \u001b[38;5;241m100\u001b[39m], shape\u001b[38;5;241m=\u001b[39mSymbolType\u001b[38;5;241m.\u001b[39mDIAMOND)\n\u001b[0;32m      9\u001b[0m     \u001b[38;5;241m.\u001b[39mset_global_opts(title_opts\u001b[38;5;241m=\u001b[39mopts\u001b[38;5;241m.\u001b[39mTitleOpts(title\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mWordCloud-shape-diamond\u001b[39m\u001b[38;5;124m\"\u001b[39m))\n\u001b[0;32m     10\u001b[0m     \u001b[38;5;241m.\u001b[39mrender( key \u001b[38;5;241m+\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_wordcloud_map_职位标签_\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m+\u001b[39m output_time\u001b[38;5;241m+\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.html\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m     11\u001b[0m )\n",
      "\u001b[1;31mNameError\u001b[0m: name 'PM_labels_words' is not defined"
     ]
    }
   ],
   "source": [
    "# 可视化词云图\n",
    "from pyecharts import options as opts\n",
    "from pyecharts.charts import WordCloud\n",
    "from pyecharts.globals import SymbolType\n",
    "\n",
    "c = (\n",
    "    WordCloud()\n",
    "    .add(\"\", PM_labels_words, word_size_range=[20, 100], shape=SymbolType.DIAMOND)\n",
    "    .set_global_opts(title_opts=opts.TitleOpts(title=\"WordCloud-shape-diamond\"))\n",
    "    .render( key +\"_wordcloud_map_职位标签_\"+ output_time+\".html\")\n",
    ")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4a2acfd",
   "metadata": {},
   "source": [
    "## 薪资-（平均薪资）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "16561a4f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [80]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# columns 重命名\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m df_PM_gz \u001b[38;5;241m=\u001b[39m \u001b[43mdf_PM_gz\u001b[49m\u001b[38;5;241m.\u001b[39mrename(columns\u001b[38;5;241m=\u001b[39m{\n\u001b[0;32m      3\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.labels\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m职位标签\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m      4\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.refreshTime\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m职位更新时间\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m      5\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.title\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m职位\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m      6\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.salary\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m薪资\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m      7\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.dq\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m地区\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m      8\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.topJob\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m是否top职位\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m      9\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.requireWorkYears\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m工作年限\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m     10\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjob.requireEduLevel\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m学历\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m     11\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compStage\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m公司融资情况\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m     12\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compName\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m公司名称\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m     13\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compIndustry\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m行业\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m     14\u001b[0m     \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcomp.compScale\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m规模\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[0;32m     15\u001b[0m })\n\u001b[0;32m     16\u001b[0m df_PM_gz\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "# columns 重命名\n",
    "df_PM_gz = df_PM_gz.rename(columns={\n",
    "    'job.labels':'职位标签',\n",
    "    'job.refreshTime':'职位更新时间',\n",
    "    'job.title':'职位',\n",
    "    'job.salary':'薪资',\n",
    "    'job.dq':'地区',\n",
    "    'job.topJob':'是否top职位',\n",
    "    'job.requireWorkYears':'工作年限',\n",
    "    'job.requireEduLevel':'学历',\n",
    "    'comp.compStage':'公司融资情况',\n",
    "    'comp.compName':'公司名称',\n",
    "    'comp.compIndustry':'行业',\n",
    "    'comp.compScale':'规模'\n",
    "})\n",
    "df_PM_gz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "30412be8",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'df_PM_gz' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [81]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m 非薪资面议 \u001b[38;5;241m=\u001b[39m \u001b[43mdf_PM_gz\u001b[49m [ \u001b[38;5;241m~\u001b[39mdf_PM_gz[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m薪资\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mstr\u001b[38;5;241m.\u001b[39mcontains(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m面议|元/天\u001b[39m\u001b[38;5;124m\"\u001b[39m)]\n\u001b[0;32m      2\u001b[0m 非薪资面议\n",
      "\u001b[1;31mNameError\u001b[0m: name 'df_PM_gz' is not defined"
     ]
    }
   ],
   "source": [
    "非薪资面议 = df_PM_gz [ ~df_PM_gz['薪资'].str.contains(\"面议|元/天\")]\n",
    "非薪资面议"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "18d53ef0",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '非薪资面议' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [82]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m 非薪资面议_detail \u001b[38;5;241m=\u001b[39m \u001b[43m非薪资面议\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m薪资\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mapply(\u001b[38;5;28;01mlambda\u001b[39;00m x:x\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m薪\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m·\u001b[39m\u001b[38;5;124m'\u001b[39m))\u001b[38;5;241m.\u001b[39mtolist()\n\u001b[0;32m      2\u001b[0m 非薪资面议_detail\n",
      "\u001b[1;31mNameError\u001b[0m: name '非薪资面议' is not defined"
     ]
    }
   ],
   "source": [
    "非薪资面议_detail = 非薪资面议['薪资'].apply(lambda x:x.split('薪')[0].split('·')).tolist()\n",
    "非薪资面议_detail"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "e6004d3a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "13.541666666666666"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(10+15)/2*13/12"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "6296b488",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '非薪资面议_detail' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [84]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m 平均薪资 \u001b[38;5;241m=\u001b[39m [ (\u001b[38;5;28mint\u001b[39m(i[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]) \u001b[38;5;241m+\u001b[39m\u001b[38;5;28mint\u001b[39m(i[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mk\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]))\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m2\u001b[39m    \\\n\u001b[0;32m      2\u001b[0m  \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(i)\u001b[38;5;241m==\u001b[39m\u001b[38;5;241m1\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mround\u001b[39m((\u001b[38;5;28mint\u001b[39m(i[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]) \u001b[38;5;241m+\u001b[39m\u001b[38;5;28mint\u001b[39m(i[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m-\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m.\u001b[39msplit(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mk\u001b[39m\u001b[38;5;124m'\u001b[39m)[\u001b[38;5;241m0\u001b[39m]))\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m2\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mint\u001b[39m(i[\u001b[38;5;241m1\u001b[39m])\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m12\u001b[39m,\u001b[38;5;241m1\u001b[39m)     \\\n\u001b[1;32m----> 3\u001b[0m  \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[43m非薪资面议_detail\u001b[49m        ] \n\u001b[0;32m      4\u001b[0m 平均薪资\n",
      "\u001b[1;31mNameError\u001b[0m: name '非薪资面议_detail' is not defined"
     ]
    }
   ],
   "source": [
    "平均薪资 = [ (int(i[0].split('-')[0]) +int(i[0].split('-')[1].split('k')[0]))/2    \\\n",
    " if len(i)==1 else round((int(i[0].split('-')[0]) +int(i[0].split('-')[1].split('k')[0]))/2*int(i[1])/12,1)     \\\n",
    " for i in 非薪资面议_detail        ] \n",
    "平均薪资"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "b7ee36c9",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '平均薪资' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [85]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[43m平均薪资\u001b[49m)\n",
      "\u001b[1;31mNameError\u001b[0m: name '平均薪资' is not defined"
     ]
    }
   ],
   "source": [
    "len(平均薪资)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "0bf7c61d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '平均薪资' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [86]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m 非薪资面议[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m平均薪资\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m=\u001b[39m\u001b[43m平均薪资\u001b[49m\n",
      "\u001b[1;31mNameError\u001b[0m: name '平均薪资' is not defined"
     ]
    }
   ],
   "source": [
    "非薪资面议['平均薪资']=平均薪资"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "7de0c864",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '非薪资面议' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [87]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43m非薪资面议\u001b[49m\n",
      "\u001b[1;31mNameError\u001b[0m: name '非薪资面议' is not defined"
     ]
    }
   ],
   "source": [
    "非薪资面议"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "5a723ae3",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name '非薪资面议' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Input \u001b[1;32mIn [88]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# 分地区平均薪资\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m 分地区_平均薪资 \u001b[38;5;241m=\u001b[39m \u001b[43m非薪资面议\u001b[49m\u001b[38;5;241m.\u001b[39mgroupby(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m地区\u001b[39m\u001b[38;5;124m'\u001b[39m)\u001b[38;5;241m.\u001b[39magg({\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m平均薪资\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmedian\u001b[39m\u001b[38;5;124m'\u001b[39m})\n\u001b[0;32m      3\u001b[0m 分地区_平均薪资\n",
      "\u001b[1;31mNameError\u001b[0m: name '非薪资面议' is not defined"
     ]
    }
   ],
   "source": [
    "# 分地区平均薪资\n",
    "分地区_平均薪资 = 非薪资面议.groupby('地区').agg({'平均薪资':'median'})\n",
    "分地区_平均薪资"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "f260e86e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[22.8, 14.0, 17.6, 17.5, 24.4, 17.9, 21.5, 17.5, 23.9, 17.5]"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "分地区_平均薪资_values =  [round(i[0],1) for i in 分地区_平均薪资.values.tolist()]\n",
    "分地区_平均薪资_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "23b5bf70",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['广州',\n",
       " '广州-从化区',\n",
       " '广州-南沙区',\n",
       " '广州-天河区',\n",
       " '广州-海珠区',\n",
       " '广州-番禺区',\n",
       " '广州-白云区',\n",
       " '广州-荔湾区',\n",
       " '广州-越秀区',\n",
       " '广州-黄埔区']"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "分地区_平均薪资_index = 分地区_平均薪资.index.tolist()\n",
    "分地区_平均薪资_index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "7144cf60",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyecharts import options as opts\n",
    "from pyecharts.charts import Bar\n",
    "from pyecharts.faker import Faker\n",
    "\n",
    "\n",
    "c = (\n",
    "    Bar()\n",
    "    .add_xaxis([i.split('-')[1] for i in 分地区_平均薪资_index[1:]])\n",
    "    .add_yaxis(\"地区\",分地区_平均薪资_values[1:])\n",
    "    .set_global_opts(\n",
    "        title_opts=opts.TitleOpts(title=\"PM-分地区-中位数薪资\"),\n",
    "        brush_opts=opts.BrushOpts(),\n",
    "    )\n",
    "    .render( key + \"_bar_with_brush_地区薪资中位数_\"+output_time+'.html')\n",
    ")\n",
    "# c.render_notebook()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "eea5da69",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>平均薪资</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>工作年限</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1-3年</th>\n",
       "      <td>12.882258</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10年以上</th>\n",
       "      <td>40.522222</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3-5年</th>\n",
       "      <td>20.531690</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5-10年</th>\n",
       "      <td>32.315432</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>一年以下</th>\n",
       "      <td>68.833333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>经验不限</th>\n",
       "      <td>31.480000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            平均薪资\n",
       "工作年限            \n",
       "1-3年   12.882258\n",
       "10年以上  40.522222\n",
       "3-5年   20.531690\n",
       "5-10年  32.315432\n",
       "一年以下   68.833333\n",
       "经验不限   31.480000"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_year_salary = 非薪资面议.groupby('工作年限').agg({'平均薪资':'mean'})\n",
    "df_year_salary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "2163b27f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>平均薪资</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>工作年限</th>\n",
       "      <th>学历</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"6\" valign=\"top\">1-3年</th>\n",
       "      <th>中专/中技</th>\n",
       "      <td>9.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>大专</th>\n",
       "      <td>11.374286</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>学历不限</th>\n",
       "      <td>22.125000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科</th>\n",
       "      <td>11.493750</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科及以上</th>\n",
       "      <td>60.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>统招本科</th>\n",
       "      <td>12.550000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"3\" valign=\"top\">10年以上</th>\n",
       "      <th>大专</th>\n",
       "      <td>60.850000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科</th>\n",
       "      <td>46.050000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>统招本科</th>\n",
       "      <td>30.180000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"6\" valign=\"top\">3-5年</th>\n",
       "      <th>大专</th>\n",
       "      <td>15.873333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>大专及以上</th>\n",
       "      <td>25.425000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>学历不限</th>\n",
       "      <td>29.925000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科</th>\n",
       "      <td>19.286000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科及以上</th>\n",
       "      <td>39.616667</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>统招本科</th>\n",
       "      <td>22.256000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"6\" valign=\"top\">5-10年</th>\n",
       "      <th>大专</th>\n",
       "      <td>23.664706</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>大专及以上</th>\n",
       "      <td>34.784615</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>学历不限</th>\n",
       "      <td>33.740000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科</th>\n",
       "      <td>28.871951</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科及以上</th>\n",
       "      <td>40.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>统招本科</th>\n",
       "      <td>42.365625</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">一年以下</th>\n",
       "      <th>学历不限</th>\n",
       "      <td>95.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科</th>\n",
       "      <td>16.500000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"6\" valign=\"top\">经验不限</th>\n",
       "      <th>大专</th>\n",
       "      <td>16.250000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>大专及以上</th>\n",
       "      <td>44.733333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>学历不限</th>\n",
       "      <td>25.566667</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科</th>\n",
       "      <td>19.340000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>本科及以上</th>\n",
       "      <td>40.766667</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>统招本科</th>\n",
       "      <td>41.800000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                  平均薪资\n",
       "工作年限  学历              \n",
       "1-3年  中专/中技   9.000000\n",
       "      大专     11.374286\n",
       "      学历不限   22.125000\n",
       "      本科     11.493750\n",
       "      本科及以上  60.000000\n",
       "      统招本科   12.550000\n",
       "10年以上 大专     60.850000\n",
       "      本科     46.050000\n",
       "      统招本科   30.180000\n",
       "3-5年  大专     15.873333\n",
       "      大专及以上  25.425000\n",
       "      学历不限   29.925000\n",
       "      本科     19.286000\n",
       "      本科及以上  39.616667\n",
       "      统招本科   22.256000\n",
       "5-10年 大专     23.664706\n",
       "      大专及以上  34.784615\n",
       "      学历不限   33.740000\n",
       "      本科     28.871951\n",
       "      本科及以上  40.000000\n",
       "      统招本科   42.365625\n",
       "一年以下  学历不限   95.000000\n",
       "      本科     16.500000\n",
       "经验不限  大专     16.250000\n",
       "      大专及以上  44.733333\n",
       "      学历不限   25.566667\n",
       "      本科     19.340000\n",
       "      本科及以上  40.766667\n",
       "      统招本科   41.800000"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 分工作时间和学历平均薪资\n",
    "df_year_edulevel =  非薪资面议.groupby(['工作年限','学历']).agg({'平均薪资':'mean'})\n",
    "df_year_edulevel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "9e3d7c57",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>平均薪资</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>行业</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>IT服务</th>\n",
       "      <td>33.733333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>专业技术服务</th>\n",
       "      <td>23.092308</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>专业服务</th>\n",
       "      <td>38.750000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>云计算/大数据</th>\n",
       "      <td>27.500000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>互联网</th>\n",
       "      <td>25.566176</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>金属制品</th>\n",
       "      <td>8.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>银行</th>\n",
       "      <td>23.500000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>食品/饮料/日化</th>\n",
       "      <td>15.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>食品/饮料/酒水</th>\n",
       "      <td>21.714286</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>餐饮业</th>\n",
       "      <td>18.875000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>63 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "               平均薪资\n",
       "行业                 \n",
       "IT服务      33.733333\n",
       "专业技术服务    23.092308\n",
       "专业服务      38.750000\n",
       "云计算/大数据   27.500000\n",
       "互联网       25.566176\n",
       "...             ...\n",
       "金属制品       8.000000\n",
       "银行        23.500000\n",
       "食品/饮料/日化  15.000000\n",
       "食品/饮料/酒水  21.714286\n",
       "餐饮业       18.875000\n",
       "\n",
       "[63 rows x 1 columns]"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 分行业\n",
    "df_industry = 非薪资面议.groupby('行业').agg({'平均薪资':'mean'})\n",
    "df_industry"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "b22612f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "with pd.ExcelWriter(key+'_'+output_time+'_.xlsx') as writer:  \n",
    "    df_year_salary.to_excel(writer, sheet_name='分工作年限平均薪资')\n",
    "    df_year_edulevel.to_excel(writer, sheet_name='分学历平均薪资')\n",
    "    df_industry.to_excel(writer, sheet_name='分行业平均薪资')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9326b535",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b4f207e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "70f92c9d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "981e1308",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "618px",
    "left": "29px",
    "top": "111.125px",
    "width": "327.188px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
